package tasks.zhuanyeji.TLV问题;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * TLV（Tag-Length-Value），是一种简单实用的数据编码方案。其数据包一般包括三个域，分别为：T域（标签Tag），L域（长度Length），V域（内容Value）。 TLV码流格式: 0001000000016f，每两位字符表示一个字节，字节均为十六进制格式，其中：
 * <p>
 * 码流中前 2 字节 0001 为 T域，紧接着 4 字节 00000001 为 L域（假设值为len，此例为 1 ），后面的len个字节 6f 为 V域； 字节序为大端序； T域最高位为 1 表示其V域内容为嵌套TLV，内容为 1 个或多个子TLV； T域最高位为 0 表示其V域内容为字符串，个数由L域的值决定。 现输入一个TLV码流（十六进制字符串格式）hexStream，请按顺序输出其中的非嵌套TLV的内容。
 * <p>
 * 输入 参数 hexStream 由字符集 [0-9a-f] 组成，12 <= hexStream.length（偶数） <= 20000
 * <p>
 * T域高位为 0 时，V域长度范围[0, 256]，V域内容为字符串（皆为可见字符）。 输入是一个合法的、完整的TLV。 输出 按顺序输出非嵌套TLV节点（即T域最高位为 0 的TLV节点）的内容；一个TLV一个字符串，格式为: level:content
 * <p>
 * level为TLV所在的嵌套级别（10进制值），取值范围 [0, 20]。 content为最终解析的value中的字符串，注意长度为 0 的输出为空串，如 1:。 样例1 复制输入： "00000000000a68656c6c6f20776f7264" 复制输出： ["0:hello word"] 解释： T域高位为 0，L域的值为 0000000a（十进制10，即：V域长度为10），V域内容为 hello word（如：68是字符h，单词之间有一个空格，共 10 个字符）
 */
public class TLV编码 {
    public static List<String> parseTLV(String hexStream) {
        List<String> result = new ArrayList<>();
        parseRecursive(hexStream, 0, 0, result);
        return result;
    }

    // 返回下一个未处理的位置
    private static int parseRecursive(String hex, int pos, int level, List<String> result) {
        while (pos < hex.length()) {
            // 读取 T: 2 字节 = 4 hex 字符
            if (pos + 4 > hex.length()) break;
            String tagHex = hex.substring(pos, pos + 4);
            int tag = Integer.parseInt(tagHex, 16);
            pos += 4;

            // 读取 L: 4 字节 = 8 hex 字符
            if (pos + 8 > hex.length()) break;
            String lenHex = hex.substring(pos, pos + 8);
            int length = (int) Long.parseLong(lenHex, 16); // 防止符号问题，用 long 再转 int
            pos += 8;

            // 读取 V: length 字节 = 2 * length hex 字符
            if (pos + 2 * length > hex.length()) break;
            String valueHex = hex.substring(pos, pos + 2 * length);
            pos += 2 * length;

            if ((tag & 0x8000) != 0) {
                // 嵌套 TLV：递归解析 value
                parseRecursive(valueHex, 0, level + 1, result);
            } else {
                // 非嵌套：转为字符串
                String content = hexToAscii(valueHex);
                result.add(level + ":" + content);
            }
        }
        return pos;
    }

    private static String hexToAscii(String hex) {
        if (hex.isEmpty()) return "";
        byte[] bytes = new byte[hex.length() / 2];
        for (int i = 0; i < bytes.length; i++) {
            String byteStr = hex.substring(2 * i, 2 * i + 2);
            bytes[i] = (byte) Integer.parseInt(byteStr, 16);
        }
        return new String(bytes, StandardCharsets.US_ASCII);
    }

    // 测试
    public static void main(String[] args) {
        String input = "00000000000a68656c6c6f20776f7264";
        List<String> output = parseTLV(input);
        System.out.println(output); // [0:hello word]
    }
}